package com.huajin.codetest.base;

import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;

/**
 * 引用(Reference)
 *
 * 从强到弱引用类型                         被垃圾回收时间                                  用途                                               生存时间
 * 强引用(StrongReference)            从来不会                                            对象的一般状态                              JVM通知运行时终止
 * 软引用(SoftReference)                 在内存不足时                                     对象缓存                                         内存不足时终止
 * 弱引用(WeakReference)              在垃圾回收时                                     对象缓存                                          GC运行后终止
 * 虚引用(PhantomReference)        未知                                                   未知                                                  未知
 *
 * 引用队列(ReferenceQueue)
 *
 * 参考：https://blog.csdn.net/u012060033/article/details/110656516
 */
public class ReferenceTest {

    public static Object object = new Object();

    public static ReferenceQueue<Object> referenceQueue = new ReferenceQueue<>();

    public static void main(String[] args) {
        //strongReference();
        //softReference();
        //weakReference();
        phantomReference();
    }

    /**
     * 如果一个对象具有StrongReference，垃圾回收器不会回收该对象，当内存空间不足时，JVM宁愿抛出OutOfMemoryError异常
     */
    public static void strongReference() {
        Object strongReference = object;
        object = null;
        System.gc();
        System.out.println(object);
        System.out.println(strongReference);
    }

    /**
     *  如果一个对象只具有oftReference，则内存空间足够，垃圾回收器就不会回收它，如果内存空间不足了，就会回收这些对象的内存
     * SoftReference通常用在对内存敏感的程序中，比如高速缓存就有用到软引用，内存够用的时候就保留，不够用就回收
     * Mybatis
     */
    public static void softReference() {
        SoftReference<Object> softReference1 = new SoftReference<>(object);
        SoftReference<Object> softReference2 = new SoftReference<>(object, referenceQueue);
        object = null;
        System.gc();
        System.out.println(object);
        System.out.println(softReference1.get());
    }

    /**
     * WeakReference不管内存是否足够，只要发生GC，都会被回收
     * 当key只有WeakReference时，GC发现后会自动清理键和值，作为简单的缓存表解决方案
     * WeakHashMap
     * ThreadLocal
     */
    public static void weakReference() {
        WeakReference<Object> weakReference = new WeakReference<>(object);
        WeakReference<Object> weakReference2 = new WeakReference<>(object, referenceQueue);
        object = null;
        System.gc();
        System.out.println(object);
        System.out.println(weakReference.get());
    }

    /**
     * PhantomReference必须和ReferenceQueue联合使用，主要用来跟踪对象被垃圾回收器回收的活动
     */
    public static void phantomReference() {
        PhantomReference<Object> phantomReference = new PhantomReference<>(object, referenceQueue);
        System.out.println(phantomReference.get());
    }

}
